Micron Document




Java ConcurrentMap
part 16/19 · 30.6 KB total
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
// Assuming oldValue is not null. This is the 'payload' operation, and should not have side-effects due to possible re-calculation on conflict
Long newValue = oldValue * C;
if (map.replace(key, oldValue, newValue))
break;
}
}

The putIfAbsent(k, v) is also useful when the entry for the key is allowed to be absent. This example could be implemented with the Java 8 compute() but it shows the overall lock-free pattern, which is more general. The replace(k,v1,v2) does not accept null parameters, so sometimes a combination of them is necessary. In other words, if v1 is null, then putIfAbsent(k, v2) is invoked, otherwise replace(k,v1,v2) is invoked.

void atomicMultiplyNullable(ConcurrentMap<Long, Long> map, Long key) {
for (;;) {
Long oldValue = map.get(key);
// This is the 'payload' operation, and should not have side-effects due to possible re-calculation on conflict
Long newValue = oldValue == null ? INITIAL_VALUE : oldValue * C;
if (replaceNullable(map, key, oldValue, newValue))
break;
}
}
...
static boolean replaceNullable(ConcurrentMap<Long, Long> map, Long key, Long v1, Long v2) {
return v1 == null ? map.putIfAbsent(key, v2) == null : map.replace(key, v1, v2);
}

──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────